package com.yuan.util.string;

import java.util.BitSet;

/**
 * Explain:     [URL编码工具类]
 * Date:        [2017/11/13 15:45]
 * Coder:       [YouYuan]
 * Version:     [1.0]
 */
public class URLEncoderUtil {

    private static BitSet dontNeedEncoding;//不进行编码的字符集

    static {
        dontNeedEncoding = new BitSet(256);
        int i;
        for (i = 'a'; i <= 'z'; i++) {
            dontNeedEncoding.set(i);
        }
        for (i = 'A'; i <= 'Z'; i++) {
            dontNeedEncoding.set(i);
        }
        for (i = '0'; i <= '9'; i++) {
            dontNeedEncoding.set(i);
        }
        dontNeedEncoding.set('+');
        dontNeedEncoding.set('-');
        dontNeedEncoding.set('_');
        dontNeedEncoding.set('.');
        dontNeedEncoding.set('*');
        dontNeedEncoding.set('{');
        dontNeedEncoding.set('}');
        dontNeedEncoding.set(':');
        dontNeedEncoding.set('\'');
        dontNeedEncoding.set('"');
    }

    /**
     * 判断字符串是否进行url编码过
     * urlEncoder即: 将' '转成'+',不编码的字符原样输出
     * 其他字符转成%XX的格式，X是16进制的字符
     * 这里会有误差,比如输入一个字符串 123+456,它到底是原文就是123+456还是123 456做了urlEncode后的内容呢？
     * 只要符合urlEncode规范的，此方法就当作已经urlEncode过了
     * @param str
     * @return 编码过返回true,否则返回false
     */
    public static boolean isEncoded(String str) {
        if (str == null) {
            return false;
        }
        char[] chars = str.toCharArray();
        for (int i = 0; i < chars.length; i++) {
            char c = chars[i];
            if (dontNeedEncoding.get((int) c)) {//判断是否是不需要编码的字符
                continue;
            }
            if (c == '%' && (i + 2) < str.length()) {
                // 判断是否符合urlEncode规范
                char c1 = chars[++i];
                char c2 = chars[++i];
                if (CharUtil.isHex(c1) && CharUtil.isHex(c2)) {//%XX的格式，X是16进制的字符
                    continue;
                }
            }
            return false;//是其它字符,则此字符串没有经过urlEncoder
        }
        return true;
    }

}
